﻿using System;
using System.Net;
using System.Windows.Threading;
using System.Collections.Generic;
using DataService.Model;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Info;
using System.ComponentModel;
using System.Windows;
using System.Threading;
using Microsoft.Phone.Net.NetworkInformation;
using System.ServiceModel.Syndication;
using System.Xml;
using System.IO;


namespace DataService
{
    public class DownloadManager : INotifyPropertyChanged
    {
        private HttpWebRequest _currentRequest;
        private bool _supportsLargeMemory;
        private TimeSpan REFRESH_TIMEOUT;
        private Dictionary<Uri, List<SyndicationItemBase>> _downloadedFeeds;

        #region Property
        private Dispatcher _dispatcher;
        public Dispatcher Dispatcher
        {
            get
            {
                return this._dispatcher;
            }
            set
            {
                this._dispatcher = value;
            }
        }

        private Exception _exception;
        public Exception LastException
        {
            get
            {
                return this._exception;
            }
            set
            {
                this._exception = value;
                this.RaisePropertyChanged("LastException");
            }
        }

        private Dictionary<string, Type> _feedMap;
        public Dictionary<string, Type> FeedMap
        {
            get
            {
                return this._feedMap;
            }
        }

        private Dictionary<string, Dictionary<string, Uri>> _feeds;
        public Dictionary<string, Dictionary<string, Uri>> Feeds
        {
            get
            {
                return this._feeds;
            }
        }

        private Dictionary<Uri, DateTime> _lastUpdated;

        private string _selectedFeed;
        public string SelectedFeed
        {
            get
            {
                return this._selectedFeed;
            }
            set
            {
                this._selectedFeed = value;
                this.RaisePropertyChanged("SelectedFeed");
            }
        }

        private int _selectedIndex;
        public int SelectedIndex
        {
            get
            {
                return this._selectedIndex;
            }
            set
            {
                this._selectedIndex = value;
                this.RaisePropertyChanged("SelectedIndex");
            }
        }

        private List<SyndicationItemBase> _selectedList;
        public List<SyndicationItemBase> SelectedList
        {
            get
            {
                return this._selectedList;
            }
            set
            {
                this._selectedList = value;
                this.RaisePropertyChanged("SelectedList");
            }
        }

        private string _selectedSite;
        public string SelectedSite
        {
            get
            {
                return this._selectedSite;
            }
            set
            {
                this._selectedSite = value;
                this.RaisePropertyChanged("SelectedSite");
            }
        }
        #endregion

        public DownloadManager()
        {
            this.REFRESH_TIMEOUT = new TimeSpan(0, 5, 0);
            this._selectedFeed = string.Empty;
            this._selectedSite = string.Empty;
            this._supportsLargeMemory = ((long)DeviceExtendedProperties.GetValue("DeviceTotalMemory") / 1024L / 1024L > 256L);
            this._feeds = new Dictionary<string, Dictionary<string, Uri>>();
            this._feedMap = new Dictionary<string, Type>();
            this._dispatcher = Deployment.Current.Dispatcher;
        }

        private static void AddObject(string key, object data)
        {
            if (PhoneApplicationService.Current.State.ContainsKey(key))
            {
                PhoneApplicationService.Current.State.Remove(key);
            }
            PhoneApplicationService.Current.State.Add(key, data);
        }

        private void DumpMemory(string callstack)
        {
            long num = (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage");
            long arg_1F_0 = num / 1024L / 1024L;
        }

        public bool IsFeedExpired(Uri feed)
        {
            return this._downloadedFeeds == null || !this._downloadedFeeds.ContainsKey(feed) || DateTime.Now - this._lastUpdated[feed] > this.REFRESH_TIMEOUT;
        }

        public void OnActivated()
        {
            this.SelectedFeed = DownloadManager.RetrieveObject<string>("SelectedFeed");
            this.SelectedSite = DownloadManager.RetrieveObject<string>("SelectedSite");
            this.SelectedIndex = DownloadManager.RetrieveObject<int>("SelectedIndex");
            if (!string.IsNullOrEmpty(this.SelectedFeed))
            {
                this.QueueRead(new Uri(this.SelectedFeed), 0);
            }
        }

        public void OnDeactivated()
        {
            DownloadManager.AddObject("SelectedIndex", this.SelectedIndex);
            DownloadManager.AddObject("SelectedFeed", this.SelectedFeed);
            DownloadManager.AddObject("SelectedSite", this.SelectedSite);
        }

        private void OnDownloadCompleted(IAsyncResult asynchronousResult)
        {
            Uri uri = asynchronousResult.AsyncState as Uri;
            try
            {
                HttpWebResponse httpWebResponse = this._currentRequest.EndGetResponse(asynchronousResult) as HttpWebResponse;
                this._currentRequest = null;
                if (this._downloadedFeeds == null)
                {
                    this._downloadedFeeds = new Dictionary<Uri, List<SyndicationItemBase>>();
                }
                if (this._lastUpdated == null)
                {
                    this._lastUpdated = new Dictionary<Uri, DateTime>();
                }
                Stream responseStream = httpWebResponse.GetResponseStream();
                using (XmlReader xmlReader = XmlReader.Create(responseStream))
                {
                    try
                    {
                        SyndicationFeed syndicationFeed = SyndicationFeed.Load(xmlReader);
                        List<SyndicationItemBase> list = new List<SyndicationItemBase>();
                        int num = 0;
                        using (IEnumerator<SyndicationItem> enumerator = syndicationFeed.Items.GetEnumerator())
                        {
                            while (enumerator.MoveNext())
                            {
                                SyndicationItem current = enumerator.Current;
                                list.Add(Activator.CreateInstance(this._feedMap[this.SelectedSite], new object[] { current }) as SyndicationItemBase);
                                num++;
                                if (!this._supportsLargeMemory && num > 10)
                                {
                                    break;
                                }
                            }
                        }
                        this.SetFeed(list, uri);
                    }
                    catch (Exception arg_EC_0)
                    {
                        Exception exception = arg_EC_0;
                        Console.WriteLine(exception.Message);
                    }
                }
                responseStream.Close();
            }
            catch (WebException arg_110_0)
            {
                WebException webException = arg_110_0;
                if (webException.Status != WebExceptionStatus.Pending)
                {
                    this.LastException = webException;
                }
            }
            this.DumpMemory("OnDownloadCompleted_Finaly");
        }

        public void QueueRead(Uri feed, int delay)
        {
            this.DumpMemory("QueueRead");
            if (this._currentRequest != null)
            {
                this._currentRequest.Abort();
            }
            this.SelectedFeed = feed.AbsoluteUri;
            ThreadPool.QueueUserWorkItem(delegate(object o)
            {
                if (!this.IsFeedExpired(feed))
                {
                    this.SetFeed(this._downloadedFeeds[feed], feed);
                    return;
                }
                if (NetworkInterface.GetIsNetworkAvailable())
                {
                    try
                    {
                        Thread.Sleep(delay);
                        this._currentRequest = (WebRequest.Create(feed) as HttpWebRequest);
                        this._currentRequest.BeginGetResponse(new AsyncCallback(this.OnDownloadCompleted), feed);
                        return;
                    }
                    catch (WebException we)
                    {
                        WebException lastException = we;
                        this.LastException = lastException;
                        return;
                    }
                    catch (NotSupportedException)
                    {
                        return;
                    }
                }
                this.Dispatcher.BeginInvoke(delegate
                {
                    if (MessageBox.Show("No network access detected.  This program requires a network connection.  Please try again later.") == MessageBoxResult.No)
                    {
                        throw new InvalidOperationException();
                    }
                }
                );
            }
            );
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string name)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(null, new PropertyChangedEventArgs(name));
            }
        }

        private static T RetrieveObject<T>(string key)
        {
            T result = default(T);
            if (PhoneApplicationService.Current.State.ContainsKey(key))
            {
                result = (T)PhoneApplicationService.Current.State[key];
            }
            return result;
        }

        private void SetFeed(List<SyndicationItemBase> items, Uri uri)
        {
            this._downloadedFeeds[uri] = items;
            this._lastUpdated[uri] = DateTime.Now;
            this.DumpMemory("SetFeed");
            this.SelectedList = items;
        }

        
    }
}
